package com.taomus.mytools.lang.clojure;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.taomus.mytools.lang.IInvoke;
import com.taomus.mytools.lang.IMethod;

import clojure.java.api.Clojure;
import clojure.lang.IFn;

public class ClojureMethod implements IMethod {
	private Object ns = null;

	public ClojureMethod(final Object ns) {
		this.ns = ns;
	}

	public IInvoke getMethod(String name) {
		return new ClojureInvoke(Clojure.var(this.ns, name),name);
	}

	public static class ClojureInvoke implements IInvoke{
		private static Logger logger = LoggerFactory.getLogger(IInvoke.class);
		private IFn fn = null;
		private String name = "";

		public ClojureInvoke(final IFn fn,String name) {
			this.name = name;
			this.fn = fn;
		}

		public Object invoke() {
			logger.debug("invoke "+name);
			return this.fn.invoke();
		}

		public Object invoke(Object... args) {
			logger.debug("invoke "+name);
			Object ret = null;
			switch (args.length) {
			case 1:
				ret = this.fn.invoke(args[0]);
				break;
			case 2:
				ret = this.fn.invoke(args[0], args[1]);
				break;
			case 3:
				ret = this.fn.invoke(args[0], args[1], args[2]);
				break;
			case 4:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3]);
				break;
			case 5:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4]);
				break;
			case 6:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5]);
				break;
			case 7:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6]);
				break;
			case 8:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7]);
				break;
			case 9:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8]);
				break;
			case 10:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9]);
				break;
			case 11:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10]);
				break;
			case 12:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11]);
				break;
			case 13:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12]);
				break;
			case 14:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13]);
				break;
			case 15:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13], args[14]);
				break;
			case 16:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13], args[14],
						args[15]);
				break;
			case 17:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13], args[14],
						args[15], args[16]);
				break;
			case 18:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13], args[14],
						args[15], args[16], args[17]);
				break;
			case 19:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13], args[14],
						args[15], args[16], args[17], args[18]);
				break;
			case 20:
				ret = this.fn.invoke(args[0], args[1], args[2], args[3],
						args[4], args[5], args[6], args[7], args[8], args[9],
						args[10], args[11], args[12], args[13], args[14],
						args[15], args[16], args[17], args[18], args[19]);
				break;
			default:
				Object args2 = new Object[args.length - 20];
				for (int i = 20; i < args.length; i++) {
					args[i] = args[i];
				}
				ret = this.fn
						.invoke(args[0], args[1], args[2], args[3], args[4],
								args[5], args[6], args[7], args[8], args[9],
								args[10], args[11], args[12], args[13],
								args[14], args[15], args[16], args[17],
								args[18], args[19], args2);
			}
			return ret;
		}

	}

}
